home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagg_m.zip / JOYSTICK.SWG / 0009_Joystick Reading.pas < prev    next >
Pascal/Delphi Source File  |  1994-02-09  |  8KB  |  167 lines

  1. {
  2. The basic approach to reading a joystick is to monitor port 201h.  The eight
  3. bits at that port correspond to:
  4.  
  5. 01h - Joystick A, "X" position
  6. 02h - Joystick A, "Y" position
  7. 04h - Joystick B, "X" position
  8. 08h - Joystick B, "Y" position
  9. 10h - Joystick A, button 1
  10. 20h - Joystick A, button 2
  11. 40h - Joystick B, button 1
  12. 80h - Joystick B, button 2
  13.  
  14. The buttons are easy: a bit of "0" means "pressed" and "1" means "not
  15. pressed".  But a single bit to read a joystick position?!?  Here's what
  16. you do:
  17.  
  18. 1)  Write a value -- any value -- to port 201h.  The four lowest bits
  19.     will then all assume a value of "1".
  20.  
  21. 2)  Start a counter, and see how many iterations it takes for your
  22.     desired bit to go to zero.  The number of iterations = the joystick
  23.     position, with lower values corresponding to "left" or "up" and
  24.     higher values corresponding to "right" or "down".
  25.  
  26. Like any joystick code, thess routines return the button statuses and the
  27. joystick positions.  They also return boolean indicators of whether the
  28. stick is left or right, up or down, based on a sensitivity you define.
  29.  
  30. The routines you call are:
  31.  
  32. procedure calibrate(r: real) -- Call this at the beginning of your program.
  33.                                 Determines presence of joysticks and how
  34.                                 far the stick has to be moved to constitute
  35.                                 L/R/U/D.  "r" is a real value from 0 to 1;
  36.                                 a value of 0.25 means that the stick has to
  37.                                 move 25% from center to count as L/R/U/D.
  38. procedure readsticks         -- Reads sticks and buttons.  Call this once
  39.                                 every round of play or whatever.
  40.  
  41. THE CODE:
  42. {--------------------------------------------------------------------------}
  43. unit joystick;
  44.  
  45. interface
  46.  
  47. var jax, jay, jbx, jby: word;                 { Joystick positions }
  48.     ja1, ja2, jaleft, jaright, jaup, jadown,  { JA1, JA2, JB1, JB2 = buttons }
  49.     jb1, jb2, jbleft, jbright, jbup, jbdown,  { GotJoystickA/B record which }
  50.     gotjoysticka, gotjoystickb: boolean;      {   joysticks are present }
  51.  
  52.    { lefts, rights, ups, downs are determined when the joysticks are read:
  53.        if the stick is sufficiently off-center, L, R, U, and/or D will be
  54.        flagged appropriately }
  55.  
  56. procedure readsticks;                         { reads joysticks }
  57. procedure calibrate(offcenterthresh: real);   { determines what stick values
  58.                                                   constitute L/R/U/D }
  59. {--------------------------------------------------------------------------}
  60. implementation
  61.  
  62. var jal, jar, jau, jad, jbl, jbr, jbu, jbd: word;   { thresholds for L/R/U/D }
  63. {--------------------------------------------------------------------------}
  64. procedure calibrate(offcenterthresh: real);   { get base figures for sticks }
  65. begin
  66.   gotjoysticka := true;                       { initially assume both sticks }
  67.   gotjoystickb := true;                       {   are present }
  68.   readsticks;                                 { get stick positions }
  69.   gotjoysticka := (jax > 0) or (jay > 0);     { if joystick reads as position }
  70.   gotjoystickb := (jbx > 0) or (jby > 0);     {   (0,0), it doesn't exist }
  71.   jal := round(jax*(1 - offcenterthresh));    { OFFCENTERTHRESH is a real }
  72.   jar := round(jax*(1 + offcenterthresh));    {   from 0 to 1 that tells the }
  73.   jau := round(jay*(1 - offcenterthresh));    {   system how far off-center }
  74.   jad := round(jay*(1 + offcenterthresh));    {   the stick has to be to get }
  75.   jbl := round(jbx*(1 - offcenterthresh));    {   counted as L/R/U/D.  For }
  76.   jbr := round(jbx*(1 + offcenterthresh));    {   example, a value of "0.25" }
  77.   jbu := round(jby*(1 - offcenterthresh));    {   means the stick has to be }
  78.   jbd := round(jby*(1 + offcenterthresh));    {   25% below base to be L / U, }
  79.   end;                                        {   or 25% above to be R / D. }
  80.  
  81. procedure readsticks;                       { Reads sticks & buttons. }
  82. var gotax, gotay, gotbx, gotby: boolean;    { whether we have a stick value }
  83.     cnter: word;                            { just a counter }
  84. begin
  85.   if gotjoysticka or gotjoystickb then begin  { if no sticks, skip reading them }
  86.     ja1 := (port[$201] and $10) = 0;          { read the buttons }
  87.     ja2 := (port[$201] and $20) = 0;
  88.     jb1 := (port[$201] and $40) = 0;
  89.     jb2 := (port[$201] and $80) = 0;
  90.     gotax := not gotjoysticka;              { Flags: do we have values yet? }
  91.     gotay := not gotjoysticka;              { Set to "true" for nonexistent }
  92.     gotbx := not gotjoystickb;              {   stick -- no need to give    }
  93.     gotby := not gotjoystickb;              {   them a second thought }
  94.     jax := 0;                               { set actual stick positions to }
  95.     jay := 0;                               {   zero -- on "existing" sticks }
  96.     jbx := 0;                               {   the number will increase }
  97.     jby := 0;
  98.     asm
  99.       mov  cx, 0000h   { set counter to zero }
  100.       mov  al, 0fh     { AL contains "new" port value (initialized to 0fh) }
  101.       mov  ah, al      { AH contains "old" port value (initialized to 0fh) }
  102.       mov  dx, 0201h   { load up joystick port }
  103.       out  dx, al      { "prime" joystick port by writing 0fh to it }
  104.       @beginloop:      { the stick-reading loop }
  105.  
  106.       in   al, dx      { read joystick port }
  107.       and  al, 0fh     { "and" it with 0fh to "eliminate" the button bits }
  108.       cmp  al, ah      { compare to the "old" port value }
  109.       je   @endloop    { if no change, skip past position checking }
  110.  
  111.       @chkax:          { checking "X" value on joystick "A" }
  112.       cmp  gotax, 01h  { see if "gotax" equals 1: if so, we've already got }
  113.       je   @chkay      {   a reading on it, and skip to "ay" readings }
  114.       test al, 01h     { if first bit of BL is a 1: if so, we don't have a }
  115.       jnz  @chkay      {   value for "ax", so jump over to "ay" }
  116.       mov  gotax, 01h  { set boolean "gotax" to "true" }
  117.       mov  jax, cx     { record counter value }
  118.  
  119.       @chkay:          { checking "Y" value on joystick "A" }
  120.       cmp  gotay, 01h
  121.       je   @chkbx
  122.       test al, 02h
  123.       jnz  @chkbx
  124.       mov  gotay, 01h
  125.       mov  jay, cx
  126.  
  127.       @chkbx:          { checking "X" value on joystick "B" }
  128.       cmp  gotbx, 01h
  129.       je   @chkby
  130.       test al, 04h
  131.       jnz  @chkby
  132.       mov  gotbx, 01h
  133.       mov  jbx, cx
  134.  
  135.       @chkby:          { checking "Y" value on joystick "B" }
  136.       cmp  gotby, 01h
  137.       je   @endloop
  138.       test al, 08h
  139.       jnz  @endloop
  140.       mov  gotby, 01h
  141.       mov  jby, cx
  142.  
  143.       @endloop:        { counter increments and data-evaluating }
  144.       mov  ah, al      { store "new" port value as "old" value for next pass }
  145.       inc  cx          { increment counter }
  146.       cmp  cx, 65535   { compare counter to 65535 }
  147.       je   @ending     { if counter = 65535, get out of loop }
  148.       cmp  gotax, 01h  { see if we have a value for "ax"; }
  149.       jne  @beginloop  {   if not, jump to top of loop for another pass }
  150.       cmp  gotay, 01h  { check "ay" }
  151.       jne  @beginloop
  152.       cmp  gotbx, 01h  { check "bx" }
  153.       jne  @beginloop
  154.       cmp  gotby, 01h  { check "by" }
  155.       jne  @beginloop
  156.       @ending:         { we're past the end of the loop }
  157.       mov  cnter,cx    { store counter value into "Pascal" variable }
  158.       end;
  159.     end;
  160.   jaleft := (jax < jal);  jaright := (jax > jar);  { determine L/R/U/D }
  161.   jaup   := (jay < jau);  jadown  := (jay > jad);
  162.   jbleft := (jbx < jbl);  jbright := (jbx > jbr);
  163.   jbup   := (jby < jbu);  jbdown  := (jby > jbd);
  164.   end;
  165. {--------------------------------------------------------------------------}
  166.   end.
  167.